package dk.mirasola.systemtraining.bridgewidgets.shared.model;

public enum ContractBid implements Bid {
    ONE_CLUB(1, Call.CLUB),
    ONE_DIAMOND(1, Call.DIAMOND),
    ONE_HEART(1, Call.HEART),
    ONE_SPADE(1, Call.SPADE),
    ONE_NOTRUMPH(1, Call.NOTRUMPH),
    TWO_CLUB(2, Call.CLUB),
    TWO_DIAMOND(2, Call.DIAMOND),
    TWO_HEART(2, Call.HEART),
    TWO_SPADE(2, Call.SPADE),
    TWO_NOTRUMPH(2, Call.NOTRUMPH),
    THREE_CLUB(3, Call.CLUB),
    THREE_DIAMOND(3, Call.DIAMOND),
    THREE_HEART(3, Call.HEART),
    THREE_SPADE(3, Call.SPADE),
    THREE_NOTRUMPH(3, Call.NOTRUMPH),
    FOUR_CLUB(4, Call.CLUB),
    FOUR_DIAMOND(4, Call.DIAMOND),
    FOUR_HEART(4, Call.HEART),
    FOUR_SPADE(4, Call.SPADE),
    FOUR_NOTRUMPH(4, Call.NOTRUMPH),
    FIVE_CLUB(5, Call.CLUB),
    FIVE_DIAMOND(5, Call.DIAMOND),
    FIVE_HEART(5, Call.HEART),
    FIVE_SPADE(5, Call.SPADE),
    FIVE_NOTRUMPH(5, Call.NOTRUMPH),
    SIX_CLUB(6, Call.CLUB),
    SIX_DIAMOND(6, Call.DIAMOND),
    SIX_HEART(6, Call.HEART),
    SIX_SPADE(6, Call.SPADE),
    SIX_NOTRUMPH(6, Call.NOTRUMPH),
    SEVEN_CLUB(7, Call.CLUB),
    SEVEN_DIAMOND(7, Call.DIAMOND),
    SEVEN_HEART(7, Call.HEART),
    SEVEN_SPADE(7, Call.SPADE),
    SEVEN_NOTRUMPH(7, Call.NOTRUMPH);

    ContractBid() {
    }

    static {
        for (int i = 0; i < values().length; i++) {
            values()[i].id = i;
        }
    }

    public static ContractBid get(int bidId) {
        return values()[bidId];
    }

    public static ContractBid get(int level, Call call) {
        for (ContractBid bidTO : values(level)) {
            if (bidTO.getCall() == call) {
                return bidTO;
            }
        }
        throw new RuntimeException();
    }

    public static ContractBid[] values(int level) {
        if (level < 1 || level > 7)
            throw new RuntimeException("level must be int between 1 and 7");
        switch (level) {
            case 1:
                return new ContractBid[]{ONE_CLUB, ONE_DIAMOND, ONE_HEART, ONE_SPADE, ONE_NOTRUMPH};
            case 2:
                return new ContractBid[]{TWO_CLUB, TWO_DIAMOND, TWO_HEART, TWO_SPADE, TWO_NOTRUMPH};
            case 3:
                return new ContractBid[]{THREE_CLUB, THREE_DIAMOND, THREE_HEART, THREE_SPADE, THREE_NOTRUMPH};
            case 4:
                return new ContractBid[]{FOUR_CLUB, FOUR_DIAMOND, FOUR_HEART, FOUR_SPADE, FOUR_NOTRUMPH};
            case 5:
                return new ContractBid[]{FIVE_CLUB, FIVE_DIAMOND, FIVE_HEART, FIVE_SPADE, FIVE_NOTRUMPH};
            case 6:
                return new ContractBid[]{SIX_CLUB, SIX_DIAMOND, SIX_HEART, SIX_SPADE, SIX_NOTRUMPH};
            case 7:
                return new ContractBid[]{SEVEN_CLUB, SEVEN_DIAMOND, SEVEN_HEART, SEVEN_SPADE, SEVEN_NOTRUMPH};
        }
        throw new RuntimeException();
    }

    public enum Call {
        CLUB, DIAMOND, HEART, SPADE, NOTRUMPH;

        public boolean isMajor() {
            return (this == HEART || this == SPADE);
        }

        public boolean isMinor() {
            return (this == CLUB || this == DIAMOND);
        }

        public boolean isNoTrumph() {
            return (this == NOTRUMPH);
        }
    }


    private int level;
    private Call call;
    private int id;

    private ContractBid(int level, Call call) {
        this.level = level;
        this.call = call;
    }

    public int getLevel() {
        return level;
    }

    public Call getCall() {
        return call;
    }

    public boolean isMajor() {
        return call.isMajor();
    }

    public boolean isMinor() {
        return call.isMinor();
    }

    public boolean isNoTrumph() {
        return call.isNoTrumph();
    }


    public boolean isHigher(ContractBid contractBid) {
        return this.compareTo(contractBid) > 0;
    }

    public boolean isLower(ContractBid contractBid) {
        return this.compareTo(contractBid) < 0;
    }

    public int getId() {
        return id;
    }
}
